package com.android.gtravelling;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;

import com.android.route.DrawPath2Point;
import com.android.route.MyItemOverlay;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

public class GoogleMapProjectActivity extends MapActivity implements
		OnClickListener {
	/** Called when the activity is first created. */
	MapView mapView;
	MapController mapController;
	ImageButton searchButton;
	ImageButton infoButton;
	EditText inputData;
	LinearLayout searchLayout;

	ListView resultList;

	long start = 0;
	long stop = 0;
	int x = 0;
	int y = 0;

	GeoPoint getGeoPoint;
	Geocoder geocoder;
	GeoPoint point;
	GeoPoint startPoint;
	GeoPoint stopPoint;
	private GeoPoint gpsPoint;
	List<Address> addresses;

	MyItemOverlay myItemOverlay;
	MyItemOverlay myItemSourcePoint;
	MyItemOverlay myItemDestinationPoint;

	final int ADD_MARKER_ITEM = 0;
	final int ADD_FROM_LOCATION = 1;
	final int ADD_TO_LOCATION = 2;
	final int SATELLITE_VIEW = 3;
	final int TRAFFIC_VIEW = 4;
	final int GET_ADD = 5;
	final int BACK_MAP = 6;
	final int DIRECT_TO_THERE = 7;

	int countColor = 0;
	int colorLine;

	int positionAddress;
	int selectContextMenu = 0;
	int flag = 0;

	String name;
	String description;
	String[] desinfo;
	private int isStart = 0;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.mapview);

		searchButton = (ImageButton) findViewById(R.id.buttonSearch);
		searchButton.setOnClickListener(GoogleMapProjectActivity.this);
		infoButton = (ImageButton) findViewById(R.id.buttonInfo);
		infoButton.setOnClickListener(GoogleMapProjectActivity.this);

		inputData = (EditText) findViewById(R.id.inputData);

		searchLayout = (LinearLayout) findViewById(R.id.searchLayout);

		resultList = (ListView) findViewById(R.id.resultList);
		resultList.setOnItemLongClickListener(new OnItemLongClickListener() {
			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
					int position, long arg3) {
				// TODO Auto-generated method stub
				selectContextMenu = 0;
				positionAddress = position;
				registerForContextMenu(resultList);
				return false;
			}
		});

		mapView = (MapView) findViewById(R.id.mapView);
		mapView.setLongClickable(true);
		registerForContextMenu(mapView);
		mapView.setBuiltInZoomControls(true);

		mapController = mapView.getController();

		Drawable marker = getResources().getDrawable(R.drawable.address);
		myItemOverlay = new MyItemOverlay(marker);
		Drawable markerStartPoint = getResources().getDrawable(
				R.drawable.source);
		myItemSourcePoint = new MyItemOverlay(markerStartPoint);
		Drawable markerStopPoint = getResources().getDrawable(
				R.drawable.destination);
		myItemDestinationPoint = new MyItemOverlay(markerStopPoint);

		MapOverlay mapOverlay = new MapOverlay();
		List<Overlay> listOverlay = mapView.getOverlays();
		listOverlay.clear();
		listOverlay.add(mapOverlay);
		mapView.invalidate();

		LocationManager mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		LocationListener mlocListener = new MyLocationListener();
		mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
				mlocListener);
	}

	public class MyLocationListener implements LocationListener {
		@Override
		public void onLocationChanged(Location loc) {
			loc.getLatitude();
			loc.getLongitude();
			String Text = "My current location is: " + "Latitud = "
					+ loc.getLatitude() + "Longitud = " + loc.getLongitude();
			Toast.makeText(getApplicationContext(), Text, Toast.LENGTH_SHORT)
					.show();
			System.out.println(Text);
			Bundle extras = getIntent().getExtras();
			String tam = extras.getString(Intent.EXTRA_TEXT);
			String searchText = extras.getString("searchText", "");
			SearchAction(searchText, 8);

			gpsPoint = new GeoPoint((int) (loc.getLatitude() * 1E6),
					(int) (loc.getLongitude() * 1E6));
			selectContextMenu = 0;
			positionAddress = 0;
			isStart = 1;
			mapView.showContextMenu();
		}

		@Override
		public void onProviderDisabled(String provider) {
			Toast.makeText(getApplicationContext(), "Gps Disabled",
					Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onProviderEnabled(String provider) {
			Toast.makeText(getApplicationContext(), "Gps Enabled",
					Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}

	private void SearchAction(String searchText, int isVisible) {

		ConvertUnsigned conv=new ConvertUnsigned();
		String temp=conv.ConvertStringURI(searchText);
		String addressLine = "";
		List<String> items = new ArrayList<String>();
		geocoder = new Geocoder(GoogleMapProjectActivity.this,
				Locale.getDefault());
		try {
			addresses = geocoder.getFromLocationName(temp, 5);
			if (addresses.size() > 0) {
				for (int i = 0; i < addresses.size(); i++) {
					for (int j = 0; j <= addresses.get(i)
							.getMaxAddressLineIndex(); j++) {
						addressLine += addresses.get(i).getAddressLine(j) + ",";
					}
					items.add(addressLine);
					addressLine = "";
				}
				setListItems(items);
				resultList.setVisibility(isVisible);
			} else {
				Toast.makeText(getBaseContext(), "Address not found!",
						Toast.LENGTH_LONG).show();
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	@Override
	public void onClick(View view) {
		// TODO Auto-generated method stub
		if (view.getId() == R.id.buttonSearch) {
			String searchText = "";
			searchText = inputData.getText().toString();
			SearchAction(searchText, 0);
		}
		if (view.getId() == R.id.buttonInfo) {
			if (flag == 0) {
				resultList.setVisibility(0);
				flag = 1;
			} else {
				resultList.setVisibility(8);
				flag = 0;
			}
		}
	}

	class MapOverlay extends Overlay {

		@Override
		public boolean onTouchEvent(MotionEvent e, MapView map) {
			// TODO Auto-generated method stub
			if (e.getAction() == MotionEvent.ACTION_DOWN) {
				start = e.getEventTime();
				x = (int) e.getX();
				y = (int) e.getY();
				getGeoPoint = mapView.getProjection().fromPixels(x, y);
				if (e.getY() < 100) {
					searchLayout.setVisibility(0);
				} else {
					searchLayout.setVisibility(8);
				}

			}
			if (e.getAction() == MotionEvent.ACTION_UP) {
				stop = e.getEventTime();
			}
			if (stop - start > 700) {
				selectContextMenu = 1;
				mapView.showContextMenu();
			}

			return false;
		}
	}

	private void setListItems(List<String> itemsList) {
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, itemsList);
		resultList.setAdapter(adapter);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		// từ vị trí của item trong list sao lấy được tọa độ?
		if (selectContextMenu == 0) {
			getGeoPoint = new GeoPoint((int) (addresses.get(positionAddress)
					.getLatitude() * 1E6), (int) (addresses
					.get(positionAddress).getLongitude() * 1E6));
		}

		switch (item.getItemId()) {
		case ADD_MARKER_ITEM:
			mapController.animateTo(getGeoPoint);// nhảy tới điểm đó
			mapController.setZoom(15);// cho zoom in lên 15 lần
			myItemOverlay.addItem(getGeoPoint, "My location", "Add location");
			mapView.getOverlays().add(myItemOverlay);
			resultList.setVisibility(8);
			return true;
		case ADD_FROM_LOCATION:
			startPoint = getGeoPoint;
			mapController.animateTo(getGeoPoint);
			mapController.setZoom(15);
			mapController.animateTo(startPoint);
			myItemSourcePoint.addItem(startPoint, "From here!", "Start point");
			mapView.getOverlays().add(myItemSourcePoint);
			resultList.setVisibility(8);
			return true;
		case ADD_TO_LOCATION:
			setColorLine();
			stopPoint = getGeoPoint;
			mapController.animateTo(getGeoPoint);
			mapController.setZoom(15);
			mapController.animateTo(stopPoint);
			myItemDestinationPoint.addItem(stopPoint, "To here!", "Stop point");
			mapView.getOverlays().add(myItemDestinationPoint);
			DrawPath(startPoint, stopPoint, mapView);
			resultList.setVisibility(8);
			countColor++;
			if (countColor > 2)
				countColor = 0;
			return true;
		case SATELLITE_VIEW:
			mapController.animateTo(getGeoPoint);
			mapController.setZoom(15);
			mapView.setStreetView(false);
			mapView.setTraffic(false);
			mapView.setSatellite(true);
			resultList.setVisibility(8);
			return true;
		case TRAFFIC_VIEW:
			mapController.animateTo(getGeoPoint);
			mapController.setZoom(15);
			// in fact,i shoudn't use setstreetview(true/false) because it's
			// maybe NOT support your location
			mapView.setStreetView(false);
			mapView.setSatellite(false);
			mapView.setTraffic(true);
			resultList.setVisibility(8);
			return true;
		case BACK_MAP:
			return true;
		case GET_ADD:
			GetAddressFromLocation();
			return true;
		case DIRECT_TO_THERE:
			setColorLine();
			stopPoint = getGeoPoint;
			mapController.animateTo(getGeoPoint);
			mapController.setZoom(15);
			mapController.animateTo(stopPoint);
			myItemDestinationPoint.addItem(stopPoint, "To here!", "Stop point");
			mapView.getOverlays().add(myItemDestinationPoint);
			DrawPath(gpsPoint, stopPoint, mapView);
			resultList.setVisibility(8);
			countColor++;
			isStart = 0;
			if (countColor > 2)
				countColor = 0;
			return true;
		default:
			return false;
		}
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		// TODO Auto-generated method stub
		menu.add(0, ADD_MARKER_ITEM, 0, "Mark here");
		if (isStart == 0) {
			menu.add(0, ADD_FROM_LOCATION, 1, "From here");
			if (startPoint != null) {
				menu.add(0, ADD_TO_LOCATION, 2, "To Here");
			}
			menu.add(0, GET_ADD, 3, "Get Address");
			if (mapView.isSatellite())
				menu.add(0, TRAFFIC_VIEW, 4, "Set traffic view here");
			else
				menu.add(0, SATELLITE_VIEW, 4, "Set satellite view here");
			menu.add(0, BACK_MAP, 5, "Back");
		}
		menu.add(0, DIRECT_TO_THERE, 6, "Direction to there");
		super.onCreateContextMenu(menu, v, menuInfo);
	}

	public String getUrl(double fromLat, double fromLon, double toLat,
			double toLon) {// connect to map web service
		StringBuffer urlString = new StringBuffer();
		urlString.append("http://maps.google.com/maps?f=d&hl=en");
		urlString.append("&saddr=");// from
		urlString.append(Double.toString(fromLat));
		urlString.append(",");
		urlString.append(Double.toString(fromLon));
		urlString.append("&daddr=");// to
		urlString.append(Double.toString(toLat));
		urlString.append(",");
		urlString.append(Double.toString(toLon));
		urlString.append("&ie=UTF8&0&om=0&output=kml");
		return urlString.toString();
	}

	public void DrawPath(GeoPoint src, GeoPoint dest, MapView mMapView) {
		List<String> items = new ArrayList<String>();
		StringBuilder urlString = new StringBuilder();
		urlString.append("http://maps.google.com/maps?f=d&hl=vi");
		urlString.append("&saddr=");
		urlString.append(Double.toString((double) src.getLatitudeE6() / 1.0E6));
		urlString.append(",");
		urlString
				.append(Double.toString((double) src.getLongitudeE6() / 1.0E6));
		urlString.append("&daddr=");
		urlString
				.append(Double.toString((double) dest.getLatitudeE6() / 1.0E6));
		urlString.append(",");
		urlString
				.append(Double.toString((double) dest.getLongitudeE6() / 1.0E6));
		urlString.append("&ie=UTF8&0&om=0&output=kml");
		Document doc = null;
		HttpURLConnection urlConnection = null;
		URL url = null;
		try {
			url = new URL(urlString.toString());
			urlConnection = (HttpURLConnection) url.openConnection();
			urlConnection.setRequestMethod("GET");
			urlConnection.setDoOutput(true);
			urlConnection.setDoInput(true);
			urlConnection.connect();

			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			doc = db.parse(urlConnection.getInputStream());

			if (doc.getElementsByTagName("GeometryCollection").getLength() > 0) {
				String path = doc.getElementsByTagName("GeometryCollection")
						.item(0).getFirstChild().getFirstChild()
						.getFirstChild().getNodeValue();
				String[] pairs = path.split(" ");
				String[] lngLat = pairs[0].split(",");
				GeoPoint startGP = new GeoPoint(
						(int) (Double.parseDouble(lngLat[1]) * 1E6),
						(int) (Double.parseDouble(lngLat[0]) * 1E6));
				mMapView.getOverlays().add(
						new DrawPath2Point(startGP, startGP, colorLine));
				GeoPoint gp1;
				GeoPoint gp2 = startGP;
				for (int i = 1; i < pairs.length; i++) {
					lngLat = pairs[i].split(",");
					gp1 = gp2;
					gp2 = new GeoPoint(
							(int) (Double.parseDouble(lngLat[1]) * 1E6),
							(int) (Double.parseDouble(lngLat[0]) * 1E6));
					mMapView.getOverlays().add(
							new DrawPath2Point(gp1, gp2, colorLine));
				}
				mMapView.getOverlays().add(
						new DrawPath2Point(dest, dest, colorLine));
			}
			NodeList nodesPlacemark = doc.getElementsByTagName("Placemark");
			NodeList nodesdesscription = doc
					.getElementsByTagName("description");
			for (int i = 0; i < nodesPlacemark.getLength() - 1; i++) {
				Element e = (Element) nodesPlacemark.item(i);
				Node nameNode = e.getElementsByTagName("name").item(0);
				name = nameNode.getFirstChild().getNodeValue();
				Element descriptionElement = (Element) nodesdesscription
						.item(i);
				description = descriptionElement.getFirstChild().getNodeValue();
				desinfo = description.split("&#160;");
				description = desinfo[0] + desinfo[1];
				desinfo = description.split("<br/>");
				description = desinfo[0];

				items.add(name + "-" + description);
			}
			setListItems(items);
			infoButton.setVisibility(0);
		} catch (Exception e) {
			// TODO: handle exception
		}

	}

	void GetAddressFromLocation() {
		Geocoder geocoder = new Geocoder(getBaseContext(), Locale.getDefault());
		List<String> items = new ArrayList<String>();
		try {
			addresses = geocoder.getFromLocation(
					getGeoPoint.getLatitudeE6() / 1E6,
					getGeoPoint.getLongitudeE6() / 1E6, 5);
			String addressLine = "";
			if (addresses.size() > 0) {
				for (int i = 0; i < addresses.size(); i++) {
					for (int j = 0; j <= addresses.get(i)
							.getMaxAddressLineIndex(); j++) {
						addressLine += addresses.get(i).getAddressLine(j) + ",";
					}
					items.add(addressLine);
					addressLine = "";
				}
				setListItems(items);
				resultList.setVisibility(0);
				infoButton.setVisibility(0);
			} else {
				Toast.makeText(getBaseContext(), "Address not found!",
						Toast.LENGTH_LONG).show();
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	void setColorLine() {
		if (countColor == 0) {
			colorLine = Color.RED;
		} else if (countColor == 1) {
			colorLine = Color.BLUE;
		} else {
			colorLine = Color.GREEN;
		}
	}

}